package cpr;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import cpr.context.Context;
import cpr.data.AR;
import cpr.data.AREntry;
import cpr.data.HLVector;
import cpr.data.SolveBestRules;
import cpr.data.SolveBestRulesEntry;

public class Main {

    /**
     * @param args
        Поме�?ти �?ти файлы в один каталог.
        Создай подкаталог html
        
        
        Подредактируй cpr.properties
        
        Либо RULES_CSV= csv файл правил
        Либо CPR_CSV=csv файл cpr
        RULES_TO_PROCESS= �?колько правил обрабатывать
        CLUSTER_THRESHOLD= кака�? "плотно�?ть" кла�?тера (1.0 - 100% правил, 0.5 - не менее половины правил, 0.1- не менее 10% правил должны на �?амом деле �?уще�?твовать)
        
        Запу�?каешь так
        java -jar cpr.jar cpr.properties
        
        Смотришь html\index.html
        
        Statistics - в�?�?ка�? �?тати�?тика - �?колько было правил, �?колько нашли кла�?теров, �?колько по времени и�?кали, �?ортировали. Еще там напечатаны найденные конфликты.
        
        Таблица - �?то �?пи�?ов найденных кла�?теров. Кликнув на кла�?тер ты увидишь внизу его ра�?печатку - 
        Какие ключи, �?колько в нем правил и т.д. В конце перечи�?лены в�?е правила, даже е�?ли из на �?амом деле не было в и�?ходном наборе правил (е�?ли CLUSTER_THRESHOLD<1.0 ). Ето так называемые COVERED RULE. Е�?ли правило к тому же еще и REAL (т.е. на�?то�?щее, не выдуманное). То печатает�?�? "real (номер и�?ходного правила)"
     * 
     */
    static long startTime, loadTime, computeMacrosTime, computeConflictTime, computeTableTime;
    static int RULES_TO_LOAD = -1;
    static int IMAGE_RULE = -1;
    static int IMAGE_SCORE = -1;
    static String IMAGE_QUBE_CSV = null;
    static String RULES_CSV = null;//"ZDU_RULE_DUMMY_last.csv";
    static String CPR_CSV = null;//"CPR_Table74.csv";
    static String HL_CSV_FILE = null;//cpr data with hierarchy
    static String HL_IMAGE = null;//cpr data with hierarchy
//    static String HL_DIGITAL = null;
    static String MODE = null;
    static boolean DIGITAL = false;
    static int BUFFER_SIZE = 10000;
    static String OUTPUT_FILE = null;
//    static BufferedWriter outputWriter = null;
    static boolean VERBOSE = false;
   // static int INITIAL_NUMBER_OF_RULES_IN_SOLUTION = 0;
    
    static Context context;
    
//    static long TIMER1;
//    static long TIMER2;
//    static long TIMER3;

    
//    public static void copy_source_data() {
//        Utils.copyRulesFromHLFile(HL_CSV, RULES_TO_LOAD);
//    }
//    
//    public static void hl_renumber() {
//    	if (true)throw new RuntimeException("deprecated");
//        String HL_DIGITAL = HL_CSV_FILE;
//    	int counter= 1;
//        int[] dec = new int[] {0,0,0,0,0};
//        String readFrom = HL_CSV_FILE;
//        String writeTo = HL_DIGITAL+".dig";
//        String dictFile = HL_DIGITAL+".dict";
//        
//        try {
//        	File df = new File(dictFile);
//        	if (df.exists()) {
//        		df.delete();
//        	}
//        } catch (Exception ex) {
//        	ex.printStackTrace();
//        }
//        int writeToIndex = -1;
//        HLVector nullvector = new HLVector(new int[] {0,0,0,0,0});
//        switch (writeToIndex) {
//        case -1:
//        	readFrom = HL_CSV_FILE;
//            writeTo = HL_DIGITAL+"1.dig";
//            writeToIndex = 2;
//            break;
//        case 1:
//        	readFrom = HL_DIGITAL+"2.dig";
//            writeTo = HL_DIGITAL+"1.dig";
//            writeToIndex = 2;
//        	break;
//        case 2:
//        	readFrom = HL_DIGITAL+"1.dig";
//            writeTo = HL_DIGITAL+"2.dig";
//            writeToIndex = 1;
//        	break;
//        }
//        counter = Utils.selectDistinct(counter, true,0, 0, readFrom, writeTo, dictFile, nullvector,RULES_TO_LOAD);
//
//        int score = Utils.getScore(dec);
//        
//        for (int hl=0;hl<5;hl++) {
//        	int len = Rule.HLH[hl].length;
//        	for (int hli=len-1;hli>0;hli--) {
//        		dec = new int[] {0,0,0,0,0};
//        		dec[hl] = hli;
//        		
//                HLVector vector = new HLVector(dec);
//                switch (writeToIndex) {
//                case -1:
//                	readFrom = HL_CSV_FILE;
//                    writeTo = HL_DIGITAL+"1.dig";
//                    writeToIndex = 2;
//                    break;
//                case 1:
//                	readFrom = HL_DIGITAL+"2.dig";
//                    writeTo = HL_DIGITAL+"1.dig";
//                    writeToIndex = 2;
//                	break;
//                case 2:
//                	readFrom = HL_DIGITAL+"1.dig";
//                    writeTo = HL_DIGITAL+"2.dig";
//                    writeToIndex = 1;
//                	break;
//                }
//                dictFile = HL_DIGITAL+".dict";
//                Rule.totalRuleNr = 0;
//                System.gc();
//                counter = Utils.selectDistinct(counter, false,hl, hli, readFrom, writeTo, dictFile, vector,RULES_TO_LOAD);
//                Printer.println(Printer.currDate()+" "+hl+"/"+hli+" free:"+Runtime.getRuntime().freeMemory()+"/"+Runtime.getRuntime().maxMemory());
//        	}
//        }
//        Printer.println("Found "+counter+" digital values.");
//        Dictionary dict = new Dictionary();
//        dict.setPath(dictFile);
//        String v1 = dict.getValueFor("32");
//        Printer.println("32="+v1);
//        
//        try {
//        	String fName = HL_DIGITAL+"1.dig";
//        	File f = new File(fName);
//        	if (fName.equals(writeTo)) {
//        		f.renameTo(new File(HL_DIGITAL+".dig"));
//        	} else {
//        	//	f.delete();
//        	}
//        	fName = HL_DIGITAL+"2.dig";
//        	f = new File(fName);
//        	if (fName.equals(writeTo)) {
//        		f.renameTo(new File(HL_DIGITAL+".dig"));
//        	} else {
//        ///		f.delete();
//        	}
//        }catch (Exception ex) {
//        	ex.printStackTrace();
//        }
//    }
    
    
//    public static void copy_qube_of_rule() {
//      Printer.println("Warning: it works only with string data");
//      Rule rule = Utils.readRuleFromHLFile(HL_CSV_FILE, IMAGE_RULE);
//        
//      int[] dec = Utils.decayScore(IMAGE_SCORE,Rule.HL_SCORE);
//        HLVector vector = new HLVector(dec);
//        if (true) throw new RuntimeException("printRuleAccordingToVectorLongOld was deleted...");
//        String si = null;//Utils.printRuleAccordingToVectorLongOld(rule, vector);
//
//        String suffix = "_rule_"+IMAGE_RULE+"_score_"+IMAGE_SCORE;
//        if (true) throw new RuntimeException("copyRulesFromHLFile was deleted...");
//        //Utils.copyRulesFromHLFile(HL_CSV_FILE, IMAGE_QUBE_CSV+suffix, si, vector);
//    }
    
//    static List _plus = new ArrayList();
//    static List _minus = new ArrayList();
  
    
    static int findIndexInRules(int ruleNr, List rules) {
        for (int i=0;i<rules.size();i++) {
            Rule aRule = (Rule) rules.get(i);
            if (aRule.ruleNr==ruleNr)  {
                if (i!=ruleNr) {
                    throw new RuntimeException("strange order");
                }
                return i;
            }
        }
        return -1;	
    }
    static AR find(int ruleNr, List list) {
        int idx = findIndex(ruleNr, list);
        if (idx==-1) return null;
        return (AR)list.get(idx);
    }
    
    static int findIndex(int ruleNr, List list) {
        for (int i=0;i<list.size();i++) {
            AR element = (AR) list.get(i);
            if (element.rule.ruleNr==ruleNr) return i;
        }
        return -1;
    }
    
    static public RenderedImage myCreateImage(List rules , int[][] cm, int scale) {
        int width = cm.length*scale;
        int height = cm.length*scale;

        int max = 0;
        for (int x = 0; x < cm.length; x++) {
            for (int y = x; y < cm.length; y++) {
                if (max<cm[x][y]) {
                    max = cm[x][y];
                }
            }
        }

        
        // Create a buffered image in which to draw
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        
        int[] rgbs = new int[scale*scale];
        for (int x = 0; x < cm.length; x++) {
            
            
            for (int y = 0; y < cm.length; y++) {

                Rule rx = (Rule)rules.get(x);
                Rule ry = (Rule)rules.get(y);
                int c1 = rx.attrValue.hashCode()%63 * 4;
                int c2 = ry.attrValue.hashCode()%63 * 4;
                int color = (c1+c2)%255;
                int color2 = 255-color;
                int color3 = 0;

                
                int value = 255-((cm[x][y] * 255)/max );
                int bl = (value * color)/ 256;
                int gr = (value * color2)/ 256;;
                int re = (value * color3)/ 256;;
                Color c= new Color(re,gr,bl);
                for (int i = 0; i < rgbs.length; i++) {
                    rgbs[i] = c.getRGB();
                }

                bufferedImage.setRGB(scale*x,scale*y,scale,scale,rgbs,0,0);
            }
        }
        return bufferedImage;
    }
    
    /*
    public static void test_perf_rule_comp() {
        int LOOPS = 10;
        Printer.println("Warning: it works only with string data");
        
        hl_rules = Utils.readRulesFromHLFile(HL_CSV_FILE, RULES_TO_LOAD,false,null);
        List list= Utils.getHLVectorList(Utils.getHLVectorIterator());
        Rule firstRule = (Rule)hl_rules.get(0);
        int c = 0;
        int t =0;
        long t1 = System.currentTimeMillis();
        for (int i=0;i<LOOPS;i++) {
            for (Iterator iter = hl_rules.iterator(); iter.hasNext();) {
                Rule aRule = (Rule)iter.next();
                Iterator hli = Utils.getHLVectorIterator();
                
                while (hli.hasNext()) {
                    HLVector vec = (HLVector)hli.next();
                    if (true) throw new RuntimeException("printRuleAccordingToVectorLongOld was deleted...");
                    
                    String s1 = null;//Utils.printRuleAccordingToVectorLongOld(firstRule, vec);
                    String s2 = null;//Utils.printRuleAccordingToVectorLongOld(aRule, vec);
                    if (s1.equals(s2)) {
                        c++;
                    }
                    t++;
                }
            }
        }
        long t2 = System.currentTimeMillis();
        Printer.print("t="+t+" c="+c+"\n");

        Printer.print(Printer.printTime(t2-t1)+"\n");

        t1 = System.currentTimeMillis();
        for (int i=0;i<LOOPS;i++) {
            for (Iterator iter = hl_rules.iterator(); iter.hasNext();) {
                Rule aRule = (Rule)iter.next();
                Iterator hli = list.iterator();
                while (hli.hasNext()) {
                    HLVector vec = (HLVector)hli.next();
                    int cmp = Utils.compareRuleAccordingToVectorLongFast(firstRule, aRule, vec);
                    if (cmp==0) {
                        c++;
                    }
                    t++;
                }
            }
        }
        t2 = System.currentTimeMillis();
        Printer.print("t="+t+" c="+c+"\n");

        Printer.print(Printer.printTime(t2-t1)+"\n");
        
        
        
    }
    /*
    public static void test_perf_instance() {
    	context.getSolveContext().bestRules = new SolveBestRules(context.getSolveContext());
    	int LOOPS = 10000000;
    	long t1 = System.currentTimeMillis();
    	for(int i=1;i<=LOOPS;i++) {
    		SolveBestRulesEntry e = new SolveBestRulesEntry();
    		e.uncovered = (int)(Math.random()*100000);
    		e.ares = new AREntry[1];
    		e.ares[0] = new AREntry();
    		e.ares[0].vector = new HLVector(new int[] {1,1,1,1,1});
    		context.getSolveContext().bestRules.add(e);
    	}
    	long t2 = System.currentTimeMillis();
    	for(int i=1;i<=LOOPS;i++) {
    		SolveBestRulesEntry e =  context.getSolveContext().bestRules.getFreeInstance();
    		e.uncovered = (int)(Math.random()*1000);
    		e.ares = new AREntry[1];
    		e.ares[0] = new AREntry();
    		e.ares[0].vector = new HLVector(new int[] {1,1,1,1,1});
    		context.getSolveContext().bestRules.add(e);
    	}
    	long t3 = System.currentTimeMillis();
    		
    	Printer.print("new  "+Printer.printTime(t2-t1)+"\n");
    	Printer.print("free "+Printer.printTime(t3-t2)+"\n");
    }
        
    public static void test_perf_eval() {
    	int MAX_ARES = 40;
    	int MAX_RECORDS = 10000;
    	int LOOPS = 100;
    	rules_number = MAX_RECORDS;
    	Iterator hli = Utils.getHLVectorIterator();
    	AREntry[] ares = new AREntry[MAX_ARES];
    	for(int i=1;i<=MAX_ARES;i++) {
    		HLVector v  = (HLVector)hli.next();
    		AREntry e = new AREntry();
    		Rule rule = new Rule();
    		rule.ruleNr = i;
    		e.rule = rule;
    		e.vector = v;
    		List plus = new ArrayList(MAX_RECORDS);
    		List minus = new ArrayList(MAX_RECORDS);
    		for (int j = 1; j <= MAX_RECORDS; j++) {
    			int m = (int)(Math.random()*3);
    			Rule rrule = new Rule();
    			rrule.ruleNr = j;
    			switch (m) {
				case 0:
					plus.add(rrule);
					break;
				case 1:
					minus.add(rrule);
					break;
				default:
					break;
				}
    		}
    		e.plus = plus;
    		e.minus = minus;
    		e.computeBinaryPlusMinus(MAX_RECORDS);
    		ares[i-1] = e;
    	}
    	long t1 = System.currentTimeMillis();
    	//Printer.print(Printer.currDate()+"\n");
    	for (int i = 0; i < LOOPS; i++) {
    		int[] c= eval_rules_old(ares);
		}
    	long t2 = System.currentTimeMillis();
    	//Printer.print(Printer.currDate()+"\n");
    	Printer.print(Printer.printTime(t2-t1)+"\n");
    	
    	 t1 = System.currentTimeMillis();
    	//Printer.print(Printer.currDate()+"\n");
    	for (int i = 0; i < LOOPS; i++) {
    		eval_rules_bin(ares);
		}
    	 t2 = System.currentTimeMillis();
    	//Printer.print(Printer.currDate()+"\n");
    	Printer.print(Printer.printTime(t2-t1)+"\n");

//    	for (int i = 0; i < c.length; i++) {
//			System.out.print(c[i]);
//		}    	
//    	
    }
    */
    public static void score_size(){
    	
    	Iterator it =Utils.getHLVectorIterator(IMAGE_SCORE);
    	int count = 0;
    	while(it.hasNext()) {
    		count++;
    		HLVector v = (HLVector)it.next();
    		Printer.println(VERBOSE, v.toString());
    	}
    	Printer.print("Different scores: "+count+"\n");
    }
    
    
    static List hl_rules = null;
    static List hl_vectors = null;
    static int min_unccovered = -1;
    
    static boolean debug = false;
    static int debugSetToTrue() {
        debug = true;
        return 1;
    }
    static int debugSetToFalse() {
        debug = false;
        return 0;
    }
 

    
//    static Candidates2 candidates2;
//    static BestRules bestRules;
//    static int[] candidatesArray;

    
    
    
    
    
    static AREntry[] copy(AREntry[] arr) {
        AREntry[] r = new AREntry[arr.length];
        for (int i = 0; i < arr.length; i++) {
            r[i] =arr[i];
        }
        return r;
    }

    
     
    
 
    static boolean eval_old(int[] c) {
        if (c==null) return false;
        boolean covered = true;
        for (int i = 0; i < c.length; i++) {
            if (c[i]<=0) {
                covered = false;
                break;
            }
        } 
        return covered;
    }
 
        
   
    public static void hl_process(CprProcessor processor, String filename, int maxRecord) {
        processor.init(filename, maxRecord);
        try {
            Reader f = new FileReader(filename);
            BufferedReader br = new BufferedReader(f);
            String s = null;
            int currentRecord = 0;
            do {
                s=br.readLine();
                if (s!=null) {
                    String[] elem = s.split("\t");
                    processor.process(s, elem);
                    currentRecord ++;
                }
                if (maxRecord>0) {
                    if (currentRecord>=maxRecord) s = null;
                }
            }while (s!=null);
            f.close();            
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        processor.finish();
    }
    
    interface CprProcessor {
        public void init(String filename, int maxRecord);
        public void process(String cprString, String[] cpr);
        public void finish();
    }

    static abstract class CprAbstractProcessor implements CprProcessor {
        String filename;
        int maxRecord;
        public void init(String filename, int maxRecord) {
            this.filename = filename;
            this.maxRecord = maxRecord;
        }
        public void finish() {
            
        }
    }
//    
//    static class CprPrintAccordingToVector extends CprAbstractProcessor {
//        HLVector vector;
//        public CprPrintAccordingToVector(HLVector vector) {
//            setVector(vector);
//        }
//        public void setVector(HLVector vector) {
//            this.vector = vector;
//        }
//        public void process(String cprString, String[] cpr) {
//            Rule aRule = Rule.createFromHLString(cprString);
//            String str = aRule.ruleNr+": "+ Utils.printRuleAccordingToVectorOld(aRule, vector);
//            Printer.println(str);
//        }
//        public void finish() {
//        }
//    }
//    
    static class CprHowManyRulesWasUsed extends CprAbstractProcessor {
        Set ruleSet = new HashSet();
        public void process(String cprString, String[] cpr) {
            String rule = cpr[12];
            ruleSet.add(rule);
        }
        public void finish() {
            int totalRulesUsed = 0;
            totalRulesUsed  = ruleSet.size();
            Printer.println("total rules used/Total lines ="+totalRulesUsed+"/"+maxRecord);
        }
    }
    
    static class CprRuleDump extends CprAbstractProcessor {
        Set ruleSet = new HashSet();
        String ruleNr;
        String[] myRule;
        public void setRuleNumber(String ruleNr) {
            this.ruleNr = ruleNr;
        }
        public void process(String cprString, String[] cpr) {
            String rule = cpr[0];
            if (rule.equals(ruleNr)) {
                myRule = cpr;
            }
        }
        
        public void finish() {
            Printer.println("["+ruleNr+"] "+myRule[1]+" "+myRule[2]+" "+myRule[3]+" "+myRule[11]+" "+myRule[4]+" "+myRule[13]+" score="+myRule[17]+" "+Printer.printScore(myRule[17]));
        }
    }
    
    static class CprRuleInfoData {
        int count = 0;
        
    }
    static class CprRuleInfo extends CprAbstractProcessor {
        Map ruleMap = new HashMap();
        public void process(String cprString, String[] cpr) {
            String rule = cpr[12];
            if (ruleMap.get(rule)==null) {
                CprRuleInfoData data = new CprRuleInfoData();
                data.count = 1;
                ruleMap.put(rule, data);
            } else {
                CprRuleInfoData data = (CprRuleInfoData)ruleMap.get(rule);
                data.count++;
            }
        }
        public void finish() {
            for (Iterator iter = ruleMap.keySet().iterator(); iter.hasNext();) {
                String rule = (String) iter.next();
                CprRuleInfoData data = (CprRuleInfoData)ruleMap.get(rule);
                Printer.print(""+rule+": "+data.count+" x ");
                CprRuleDump dump = new CprRuleDump();
                dump.setRuleNumber(rule);
                
                hl_process(dump, "data\\tab_ZDU_RULE_TABLE_S.txt",36000);
                
            }
            Printer.println("total rules ="+ruleMap.keySet().size()+" / "+maxRecord);
        }
    }
        
    public static void init(String[] args) {
    	 // Read properties file.
        Properties properties = new Properties();
        StringBuffer sb = new StringBuffer();
        
        if (args.length==0) throw new RuntimeException("Specify .properties file as parameter!");
        try {
        	Printer.print("Reading "+args[0]+" for properties\n");
            properties.load(new FileInputStream(args[0]));
            for (Enumeration iter = properties.keys(); iter.hasMoreElements();) {
                String key = (String) iter.nextElement();
                String value = properties.getProperty(key);
                Printer.print("Setting property "+key+" to "+value+"\n");
                sb.append(key+"="+value+"\n");
                CPRProperty.setProperty(key,value);
            }
        } catch (IOException e) {
        	e.printStackTrace();
        }
        Printer.setSecordWriter(CPRProperty.getOutputFilename());
        Printer.print(sb.toString());
    }
    
    public static void perform_mode(String mode) {
    	MODE = mode;
//    	if (CPRProperty.PROPERTY_MODE_VALUE_COPY.equals(mode)) {
//            copy_source_data();
//        } else 
//        	if (CPRProperty.PROPERTY_MODE_VALUE_HL_RENUMBER.equals(mode)) {
//            hl_renumber();
//        } else if (CPRProperty.PROPERTY_MODE_VALUE_HL_IMAGE_QUBE.equals(mode)) {
//            copy_qube_of_rule();
//        } else 
//        	if (CPRProperty.PROPERTY_MODE_VALUE_HL_PRINT_RECORDS_ACCORDING_TO_SCORE.equals(mode)) {
//        	Printer.println("Warning: it works only with string data");
//            
//        	int[] dec = Utils.decayScore(IMAGE_SCORE,Rule.HL_SCORE);
//            HLVector vector = new HLVector(dec);
//            Utils.printRulesFromHLFile(HL_CSV_FILE, vector,RULES_TO_LOAD);
//        } else 
        if (CPRProperty.PROPERTY_MODE_VALUE_HL_ANALYSE.equals(mode)) {
//            hl_analyse();
        } else if (CPRProperty.PROPERTY_MODE_VALUE_SCORE_SIZE.equals(mode)) {
            score_size();
//        } else if (CPRProperty.PROPERTY_MODE_VALUE_TEST_PERF_INSTANCE.equals(mode)) {
//        	test_perf_instance();
//        } else if (CPRProperty.PROPERTY_MODE_VALUE_TEST_PERF_RULE_COMP.equals(mode)) {
//        	test_perf_rule_comp();
        } else if (CPRProperty.PROPERTY_MODE_VALUE_HOW_MANY_RULES_WAS_USED.equals(mode)) {
        	Printer.println("Warning: it works only with string data");
            hl_process(new CprHowManyRulesWasUsed(), HL_CSV_FILE, RULES_TO_LOAD);
        } else if (CPRProperty.PROPERTY_MODE_VALUE_RULE_INFO.equals(mode)) {
        	Printer.println("Warning: it works only with string data");
            
            hl_process(new CprRuleInfo(), HL_CSV_FILE, RULES_TO_LOAD);
//        } else if (CPRProperty.PROPERTY_MODE_VALUE_PRINT_CPR.equals(mode)) {
//        	Printer.println("Warning: it works only with string data");
//            
//            hl_process(new CprPrintAccordingToVector(new HLVector(new int[]{5,4,4,3,3})), HL_CSV_FILE, RULES_TO_LOAD);
        } else if (CPRProperty.PROPERTY_MODE_VALUE_RULE_INFO.equals(mode)) {
        	Printer.println("Warning: it works only with string data");
            
            hl_process(new CprRuleInfo(), HL_CSV_FILE, RULES_TO_LOAD);
        } else {
        	Printer.print("mode is not set\n");
        }
        
    }
    public static void main(String[] args) {
    	init(args);
       
    	perform_mode(MODE);
        

    }

    static class CPRProperty {
        
    	public static String PROPERTY_IMAGE_RULE = "IMAGE_RULE";
        public static String PROPERTY_IMAGE_QUBE_CSV = "IMAGE_QUBE_CSV";
        public static String PROPERTY_IMAGE_SCORE = "IMAGE_SCORE";

        public static String PROPERTY_MODE = "MODE";
        public static String PROPERTY_MODE_VALUE_HOW_MANY_RULES_WAS_USED = "HOW-MANY-RULES-WAS-USED";
        public static String PROPERTY_MODE_VALUE_RULE_INFO = "RULE-INFO";
        public static String PROPERTY_MODE_VALUE_PRINT_CPR = "PRINT-CPR";
        public static String PROPERTY_MODE_VALUE_COPY = "COPY";
        public static String PROPERTY_MODE_VALUE_DUMP_RULES = "DUMP-RULES";
//        public static String PROPERTY_MODE_VALUE_HL_RENUMBER = "HL-RENUMBER";
//        public static String PROPERTY_MODE_VALUE_HL_IMAGE_QUBE = "HL-IMAGE-CUBE";
        public static String PROPERTY_MODE_VALUE_HL_PRINT_RECORDS_ACCORDING_TO_SCORE = "HL-PRINT-RECORDS-ACCORDING-TO-SCORE";
        public static String PROPERTY_MODE_VALUE_HL_ANALYSE = "HL-ANALYSE";
        public static String PROPERTY_MODE_VALUE_SCORE_SIZE = "SCORE-SIZE";
        public static String PROPERTY_MODE_VALUE_CLUSTER_SEARCH = "CLUSTER-SEARCH";
        public static String PROPERTY_MODE_BATCH = "BATCH";
        
        
        public static String PROPERTY_MODE_VALUE_TEST_PERF_INSTANCE = "TEST-PERF-INSTANCE";
        public static String PROPERTY_MODE_VALUE_TEST_PERF_RULE_COMP = "TEST-PERF-RULE-COMP";
           
        public static String PROPERTY_VERBOSE = "VERBOSE";
        public static String PROPERTY_DIGITAL = "DIGITAL";
        public static String PROPERTY_CPR_CSV = "CPR_CSV";
        public static String PROPERTY_HL_CSV = "HL_CSV";
//        public static String PROPERTY_HL_DIGITAL = "HL_DIGITAL";
//        public static String PROPERTY_HL_DIGITAL_DICT = "HL_DIGITAL_DICT";
        public static String PROPERTY_OUTPUT_FILE = "OUTPUT_FILE";
        public static String PROPERTY_HL_IMAGE = "HL_IMAGE";
        public static String PROPERTY_BUFFER_SIZE = "BUFFER_SIZE";
        public static String PROPERTY_RULES_CSV = "RULES_CSV";
        public static String PROPERTY_RULES_TO_PROCESS = "RULES_TO_PROCESS";
        
        
        //public static String PROPERTY_INITIAL_NUMBER_OF_RULES_IN_SOLUTION = "INITIAL_NUMBER_OF_RULES_IN_SOLUTION";
        public static void setProperty(String name, String value) {
            if (PROPERTY_RULES_CSV.endsWith(name)) {
                RULES_CSV = value;
            } else if (PROPERTY_CPR_CSV.endsWith(name)) {
                CPR_CSV = value;
            } else if (PROPERTY_HL_CSV.endsWith(name)) {
                HL_CSV_FILE = value;
            } else if (PROPERTY_OUTPUT_FILE.endsWith(name)) {
           		OUTPUT_FILE = value;	
            } else if (PROPERTY_HL_IMAGE.endsWith(name)) {
                HL_IMAGE = value;
            } else if (PROPERTY_IMAGE_QUBE_CSV.endsWith(name)) {
                IMAGE_QUBE_CSV = value;
            } else if (PROPERTY_MODE.endsWith(name)) {
                MODE = value;
            } else if (PROPERTY_MODE.endsWith(name)) {
                MODE = value;
            } else if (PROPERTY_VERBOSE.endsWith(name)) {
                if ("false".equalsIgnoreCase(value)) {
                    VERBOSE = false;
                } else if ("no".equalsIgnoreCase(value)) {
                    VERBOSE = false;
                } else {
                    VERBOSE = true;
                }
            } else if (PROPERTY_DIGITAL.endsWith(name)) {
                if ("false".equalsIgnoreCase(value)) {
                    DIGITAL = false;
                } else if ("no".equalsIgnoreCase(value)) {
                    DIGITAL = false;
                } else {
                    DIGITAL = true;
                }
            } else if (PROPERTY_RULES_TO_PROCESS.endsWith(name)) {
                RULES_TO_LOAD = Integer.parseInt(value);
            } else if (PROPERTY_IMAGE_RULE.endsWith(name)) {
            	IMAGE_RULE = Integer.parseInt(value);
            } else if (PROPERTY_BUFFER_SIZE.endsWith(name)) {
            	BUFFER_SIZE = Integer.parseInt(value);
            } else if (PROPERTY_IMAGE_SCORE.endsWith(name)) {
                StringTokenizer st = new StringTokenizer(value,",");
                if (st.countTokens()==5) {
                    int[] dec = new int[5];
                    for (int i = 0; i < dec.length; i++) {
                        String s = st.nextToken();
                        dec[i] = Integer.parseInt(s);
                    }
                    HLVector vec = new HLVector(dec);
                    IMAGE_SCORE = vec.score;
                } else if (st.countTokens()==1) {
                    IMAGE_SCORE = Integer.parseInt(value);
                }
                Printer.println(""+IMAGE_SCORE);
            //} else if (PROPERTY_INITIAL_NUMBER_OF_RULES_IN_SOLUTION.endsWith(name)) {
                //INITIAL_NUMBER_OF_RULES_IN_SOLUTION = Integer.parseInt(value);
            }
        }
        
        public static String getOutputFilename() {
        	if ("auto".equals(OUTPUT_FILE)) {
        		return HL_CSV_FILE+".output";
        	} else {
        		return OUTPUT_FILE;	
        	}
        }

    }

}
